package com.project.easy.common.util.json;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.project.easy.common.util.constants.CommonConstant;
import com.project.easy.common.util.date.DateTool;
import com.project.easy.common.util.exception.print.PrintException;
import com.project.easy.common.util.string.StringUtil;

import java.io.IOException;

/**
 * @author GreatorMan.cool
 * @copyright: Copyright (c) 2020
 * @company: 扬起科技有限公司
 * @date 2021/9/6 11:46
 * @description:
 */
public final class JacksonUtil extends ObjectMapper {
    /**
     * 单例Josn 工具对象
     */
    private static JacksonUtil mapper;

    /**
     * 构造
     */
    public JacksonUtil() {
        this(JsonInclude.Include.NON_EMPTY);
    }
    /**
     * 构造工具
     * @param include
     */
    public JacksonUtil(JsonInclude.Include include) {
        // 设置输出时包含属性的风格
        if (include != null) {
            this.setSerializationInclusion(include);
        }
        // 允许单引号、允许不带引号的字段名称
        this.enableSimple();
        // 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
        this.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 空值处理为空串
        this.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
            @Override
            public void serialize(Object value, JsonGenerator jgen,
                                  SerializerProvider provider) throws IOException,
                    JsonProcessingException {
                jgen.writeString("");
            }
        });
    }
    /**
     * 创建只输出非Null且非Empty(如List.isEmpty)的属性到Json字符串的Mapper,建议在外部接口中使用.
     * @return 返回工具类
     */
    public static JacksonUtil getInstance() {
        if (mapper == null) {
            mapper = new JacksonUtil().enableSimple();
        }
        return mapper;
    }
    /**
     * Object可以是POJO
     * @param object 如果对象为Null, 返回"null".
     * @return 返回字符串
     */
    public String toJson(Object object) {
        try {
            return this.writeValueAsString(object);
        } catch (IOException e) {
            PrintException.print(e);
        }
        return CommonConstant.EMPTY_STRING;
    }
    /***
     *时间格式
     * @param object 数据
     * @return 返回字符串
     */
    public static String toDateJson(Object object) {
        JacksonUtil jsonMapper = new JacksonUtil();
        jsonMapper.setDateFormat(DateTool.getYyyyMMdd());
        return jsonMapper.toJson(object);
    }
    /**
     * 创建只输出初始值被改变的属性到Json字符串的Mapper.
     * @return 返回工具
     */
    public static JacksonUtil buildNonDefaultMapper() {
        return new JacksonUtil();
    }
    /**
     * 反序列化POJO或简单Collection如List<String>
     * @param jsonString JOSN字符串
     * @param clazz 数据类型
     * @param <T> 范湖数据
     * @return 返回对象 如果JOSN为空 则返回 null
     */
    public <T> T fromJson(String jsonString, Class<T> clazz) {
        if (StringUtil.isBlank(jsonString)) {
            return null;
        }
        try {
            return this.readValue(jsonString, clazz);
        } catch (IOException e) {
            PrintException.print(e);
            return null;
        }
    }
    /**
     * 序列化复杂Collection如List<Bean>, 先使用函數createCollectionType构造类型,然后调用本函数.
     * @param jsonString JSON 字符串
     * @param javaType 数据类型
     * @param <T> 返回数据
     * @return 返回数据
     */
    @SuppressWarnings("unchecked")
    public <T> T fromJson(String jsonString, JavaType javaType) {
        if (StringUtil.isBlank(jsonString)) {
            return null;
        }
        try {
            return (T) this.readValue(jsonString, javaType);
        } catch (IOException e) {
            PrintException.print(e);
            return null;
        }
    }
    /**
     * 构建反向数据类型
     * HashMap<String,MyBean>, 则调用(HashMap.class,String.class, MyBean.class)
     * @param beanClass 数据类型
     * @param elementClasses 泛型数据
     * @return 返回数据类型
     */
    public JavaType createCollectionType(Class<?> beanClass, Class<?>... elementClasses) {
        return this.getTypeFactory().constructParametricType(beanClass, elementClasses);
    }
    /**
     * JsonP处理
     * @param functionName 函数名称
     * @param object 数据对象
     * @return 返回数据
     */
    public String toJsonP(String functionName, Object object) {
        return toJson(new JSONPObject(functionName, object));
    }
    /**
     * 允许单引号
     * 允许不带引号的字段名称
     *  @return 对象
     */
    public JacksonUtil enableSimple() {
        this.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        this.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        return this;
    }
    /**
     * 取出Mapper做进一步的设置或使用其他序列化API
     *  @return 对象
     */
    public ObjectMapper getMapper() {
        return this;
    }
    /**
     * 转换为JSON字符串
     * @param object 数据
     * @return 返回字符串
     */
    public static String toJsonString(Object object) {
        return JacksonUtil.getInstance().toJson(object);
    }
}
